import FormData from 'form-data';
import poll from 'fermionjs/lib/poll';
import fetch, { parseJSON } from 'fermionjs/lib/fetch';
import createLogger from '@kuiper-helpers/logger';
import errorCodesBuilder from '../../helpers/errorCodesBuilder';

const log = createLogger({ alwaysCreate: true, writeFile: false });
const errorCodes = errorCodesBuilder();

export default async function monitorTaskRequest({
	api,
	checkInterval,
	payload,
	job,
	queueTaskIdField = 'taskId',
}) {
	let taskId = job.data[queueTaskIdField];
	if (taskId) {
		const checkApi = `${api}/${taskId}`;
		log.debug({ api: checkApi }, '[监测任务]检查任务是否创建');
		try {
			const resp = await fetch(checkApi);
			taskId = resp.task_id;
			log.debug({ taskId, payload, api: checkApi }, '[监测任务]任务已创建');
		} catch (error) {
			log.debug({ checkApi, payload }, `检查任务是否创建失败`);
		}
	}

	if (!taskId) {
		log.debug({ api, payload }, '[监测任务]创建任务');
		try {
			const form = new FormData();
			Object.entries(payload).forEach(([field, val]) => {
				val && form.append(field.toString(), val.toString());
			});
			const createTaskResp = await fetch(api, {
				method: 'POST',
				body: form,
			});
			taskId = createTaskResp.task_id;
		} catch (err) {
			const error = errorCodes['[02]监测Worker任务创建失败'].from(err);
			log.error({ error, api, payload }, error.internalMessage);
			throw error;
		}
		if (job) {
			job.update({ ...job.data, [queueTaskIdField]: taskId });
			job.progress(1);
		}
	}

	let response;
	const taskApi = `${api}/${taskId}`;
	await poll(async () => {
		const ret = await fetch(taskApi, {
			responseType: 'raw',
			retry: 3,
		}).catch(error => {
			log.debug({ error, api: taskApi }, '[监测任务]检查任务状态失败');
			throw error;
		});
		log.debug(
			{ payload, statusCode: ret.status, api: taskApi },
			'[监测任务]检查任务状态'
		);

		if (ret.status === 202) return false;

		response = await parseJSON(ret);

		if (ret.status > 400) {
			const error = new Error(response.msg);
			error.code = response.code;
			throw error;
		}

		return true;
	}, checkInterval);
	log.debug({ response }, '[监测任务]检查任务状态');

	return response;
}
